package com.rybbaby.tss.api.user;

import com.qiniu.storage.model.DefaultPutRet;
import com.rybbaby.tss.core.annotation.Token;
import com.rybbaby.tss.core.utils.*;
import com.rybbaby.tss.core.web.controller.BaseController;
import com.rybbaby.tss.front.tssAppUser.entity.TssAppUser;
import com.rybbaby.tss.front.tssAppUser.service.ITssAppUserService;
import com.rybbaby.tss.front.tssAppUserCorrelationBaby.entity.TssAppUserCorrelationBaby;
import com.rybbaby.tss.front.tssAppUserCorrelationBaby.service.ITssAppUserTssAppUserCorrelationBabyService;
import com.rybbaby.tss.front.tssPertainRelation.entity.TssPertainRelation;
import com.rybbaby.tss.front.tssPertainRelation.service.ITssPertainRelationService;
import com.rybbaby.tss.front.tssStudent.entity.TssStudent;
import com.rybbaby.tss.front.tssStudent.service.ITssStudentService;
import com.rybbaby.tss.platform.initializer.SysConfigInitializer;
import com.rybbaby.tss.platform.sysConfig.entity.SysConfig;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.MimeTypeUtils;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


/**
 * @author 雷春琼
 * @description 会员(宝宝 、 学生)相关API
 * @createDate 2017-08-09 下午11:50:14
 */
@CrossOrigin
@RestController
@RequestMapping(value = "api/user", produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
public class UserApi extends BaseController {

    @Autowired
    private ITssAppUserService appUserService;
    @Autowired
    private ITssAppUserTssAppUserCorrelationBabyService appUserTssAppUserCorrelationBabyService;
    @Autowired
    private ITssStudentService tssStudentService;
    @Autowired
    private ITssPertainRelationService tssPertainRelationService;

    /**
     * 添加宝宝
     *
     * @param tssStudent
     * @return
     */
    @Token(validateSign = true)
    @RequestMapping(value = "addBaby", method = RequestMethod.POST)
    public String addBaby(HttpServletRequest request,
                          @RequestParam String appUserId,
                          @RequestParam Integer relation,
                          TssStudent tssStudent) {
        String resMsg = "添加宝宝成功!";
        int resCode = 200;
        if (StringUtils.isBlank(tssStudent.getName())) {
            resMsg = "宝宝姓名必传!";
            return new AppResponse(resMsg, 301).jsonResponse(false);
        }
        if (StringUtils.isBlank(tssStudent.getBirthdayDate())) {
            resMsg = "出生日期必传!";
            return new AppResponse(resMsg, 301).jsonResponse(false);
        }
        try {
            TssAppUser appUser = this.appUserService.get(appUserId);
            if (appUser != null) {
                //上传头像
                UploadAvatarResult uploadAvatarResult = uploadAvatar(request);
                if (uploadAvatarResult != null) {
                    String avatar = uploadAvatarResult.getAvatar();
                    if (StringUtils.isNotBlank(avatar)) {
                        tssStudent.setHeadPortrait(avatar);
                    }
                }
                tssStudent.setContactPhone(appUser.getPhoneNum());
                tssStudent.setRegisterApp(true);
                tssStudent.setCreateTime(new Timestamp(System.currentTimeMillis()));
                tssStudent.setUpdateTime(new Timestamp(System.currentTimeMillis()));
                Serializable newStudentId = tssStudentService.addBaby(appUser, relation, tssStudent);
                if (newStudentId == null) {
                    resCode = 301;
                    resMsg = "添加宝宝失败!";
                    deleteUploadAvatar(uploadAvatarResult);
                }
            } else {
                resCode = 301;
                resMsg = "app用户信息不能存在!";
            }
        } catch (Exception e) {
            resCode = 500;
            String message = e.getMessage();
            resMsg = "添加宝宝成功" + (StringUtils.isNotBlank(message) ? ("(" + message + ")") : "") + "!";
            e.printStackTrace();
        }
        return new AppResponse(resMsg, resCode).jsonResponse(false);
    }

    /**
     * App端用户二维码关联宝宝
     *
     * @param appUserId App用户id
     * @param relation  关系
     * @param quickMark 二维码
     * @return
     */
    @Token(validateSign = true)
    @RequestMapping(value = "correlationBabyByQRCode", method = RequestMethod.POST)
    public String correlationBabyByQRCode(@RequestParam String appUserId,
                                          @RequestParam Integer relation,
                                          @RequestParam String quickMark) {
        String resMsg = "关联宝宝成功!";
        int resCode = 200;
        try {
            //根据二维码查询宝宝
            List<TssStudent> tssStudentList = tssStudentService.findByQuickMark(quickMark);
            if (tssStudentList != null && !tssStudentList.isEmpty()) {
                String studentId = tssStudentList.get(0).getId();
                DetachedCriteria dc = DetachedCriteria.forClass(TssAppUserCorrelationBaby.class);
                dc.add(Restrictions.eq("appUserId", appUserId));
                dc.add(Restrictions.eq("studentId", studentId));
                List<TssAppUserCorrelationBaby> correlationBabyList = this.appUserTssAppUserCorrelationBabyService.findByDetached(dc);
                if (correlationBabyList != null && !correlationBabyList.isEmpty()) {
                    resMsg = "您以已经是宝宝的家人，不需要再关联了!";
                    return new AppResponse(resMsg, 301).jsonResponse(false);
                }
                Serializable newId = this.appUserTssAppUserCorrelationBabyService.correlationBaby(appUserId, relation, studentId);
                if (newId == null) {
                    resMsg = "关联宝宝失败!";
                    return new AppResponse(resMsg, 301).jsonResponse(false);
                }
            } else {
                resMsg = "未查询到宝宝信息!";
                return new AppResponse(resMsg, 301).jsonResponse(false);
            }
        } catch (Exception e) {
            resCode = 500;
            String message = e.getMessage();
            resMsg = "关联宝宝失败" + (StringUtils.isNotBlank(message) ? ("(" + message + ")") : "") + "!";
            e.printStackTrace();
        }
        return new AppResponse(resMsg, resCode).jsonResponse(false);
    }

    /**
     * 宝宝列表
     *
     * @param appUserId app 用户Id
     * @return
     */
    @Token(validateSign = true)
    @RequestMapping(value = "babyList", method = RequestMethod.GET)
    public String babyList(@RequestParam String appUserId) {
        String resMsg = "查询宝宝列表成功!";
        int resCode = 200;
        try {
            TssAppUser appUser = this.appUserService.get(appUserId);
            if (appUser != null) {
                String phoneNum = appUser.getPhoneNum();
                //当前用户关联的宝宝
                List<TssAppUserCorrelationBaby> correlationBabies = this.appUserTssAppUserCorrelationBabyService.findByProperty("appUserId", appUserId);
                List<String> studentIds = new ArrayList<>();
                if (correlationBabies != null && !correlationBabies.isEmpty()) {
                    for (TssAppUserCorrelationBaby correlationBaby : correlationBabies) {
                        String studentId = correlationBaby.getStudentId();
                        if (StringUtils.isNotBlank(studentId)) {
                            studentIds.add(studentId);
                        }
                    }
                }
                //查询自己的宝宝和关联的宝宝
                DetachedCriteria dc = DetachedCriteria.forClass(TssStudent.class);
                if (studentIds != null && !studentIds.isEmpty()) {
                    dc.add(Restrictions.or(
                            Restrictions.eq("contactPhone", phoneNum),//学生的直接联系电话与当前APP用户电话一致的学生(自己的宝宝)
                            Restrictions.in("id", studentIds))); //查询当前用户关联的宝宝
                } else {
                    dc.add(Restrictions.eq("contactPhone", phoneNum));//学生的直接联系电话与当前APP用户电话一致的学生(自己的宝宝)
                }
                List<TssStudent> studnetList = this.tssStudentService.findByDetached(dc);
                return new AppResponse(resMsg, resCode, studnetList).jsonResponse(true);
            } else {
                resCode = -1;
                resMsg = "用户不存在！";
                return new AppResponse(resMsg, resCode).jsonResponse(false);
            }
        } catch (Exception e) {
            resCode = 500;
            String message = e.getMessage();
            resMsg = "查询宝宝列表失败" + (StringUtils.isNotBlank(message) ? ("(" + message + ")") : "") + "!";
            e.printStackTrace();
            return new AppResponse(resMsg, resCode).jsonResponse(false);
        }
    }

    /**
     * 宝宝信息
     *
     * @param studentId 宝宝id
     * @return
     */
    @Token(validateSign = true)
    @RequestMapping(value = "babyDetails", method = RequestMethod.GET)
    public String babyDetails(@RequestParam String studentId) {
        String resMsg = "查询宝宝信息成功!";
        int resCode = 200;
        try {
            TssStudent student = tssStudentService.get(studentId);
            return new AppResponse(resMsg, resCode, student).jsonResponse(true);
        } catch (Exception e) {
            resCode = 500;
            String message = e.getMessage();
            resMsg = "查询宝宝信息失败" + (StringUtils.isNotBlank(message) ? ("(" + message + ")") : "") + "!";
            e.printStackTrace();
        }
        return new AppResponse(resMsg, resCode).jsonResponse(false);
    }

    /**
     * 修改宝宝信息
     *
     * @param request   请求对象
     * @param appUserId APP用户id
     * @param relation  关系
     * @param studnet   学生对象
     * @return
     */
    @Token(validateSign = true)
    @RequestMapping(value = "changeBaby", method = RequestMethod.POST)
    public String changeBaby(HttpServletRequest request, @RequestParam String appUserId, Integer relation, TssStudent studnet) {
        String resMsg = "修改宝宝信息成功!";
        int resCode = 200;
        //上传头像
        UploadAvatarResult uploadAvatarResult = uploadAvatar(request);
        if (StringUtils.isNotBlank(uploadAvatarResult)) {
            String avatar = uploadAvatarResult.getAvatar();
            if (StringUtils.isNotBlank(avatar)) {
                studnet.setHeadPortrait(avatar);//上传了头像就改，没传就不改
            }
        }
        try {
            TssAppUser appUser = this.appUserService.get(appUserId);
            if (appUser != null) {
                String studnetId = studnet.getId();
                TssStudent tssStudent = this.tssStudentService.get(studnetId);
                if (tssStudent != null) {
                    //修改头像
                    String headPortrait = studnet.getHeadPortrait();
                    if (StringUtils.isNotBlank(headPortrait)) {
                        tssStudent.setHeadPortrait(headPortrait);
                    }
                    //修改宝宝姓名
                    String name = studnet.getName();
                    if (StringUtils.isNotBlank(name)) {
                        tssStudent.setName(name);
                    }
                    //修改宝宝昵称
                    String nickName = studnet.getNickName();
                    if (StringUtils.isNotBlank(nickName)) {
                        tssStudent.setNickName(nickName);
                    }
                    //修改宝宝性别
                    Integer sex = studnet.getSex();
                    if (sex != null) {
                        tssStudent.setSex(sex);
                    }
                    //朽败宝宝生日
                    Date birthdayDate = studnet.getBirthdayDate();
                    if (StringUtils.isNotBlank(birthdayDate)) {
                        tssStudent.setBirthdayDate(birthdayDate);
                    }
                    //修改宝宝信息
                    this.tssStudentService.updateEntitiy(tssStudent);
                    //修改家属关系
                    if (relation != null) {
                        //修改与当前APP用户手机号一致并且是当前学生家属关系（正常情况肯定只有一个）
                        DetachedCriteria dc = DetachedCriteria.forClass(TssPertainRelation.class);
                        dc.add(Restrictions.eq("studentId", studnetId));
                        dc.add(Restrictions.eq("contactPhone", appUser.getPhoneNum()));
                        List<TssPertainRelation> pertainRelations = this.tssPertainRelationService.findByDetached(dc);
                        for (TssPertainRelation pertainRelation : pertainRelations) {
                            pertainRelation.setAffiliationRelation(relation);
                        }
                        this.tssPertainRelationService.batchUpdate(pertainRelations);
                    }
                    return new AppResponse(resMsg, resCode, studnet).jsonResponse(true);
                } else {
                    throw new Exception("宝宝信息不存在!");
                }
            } else {
                throw new Exception("家长信息不存在!");
            }
        } catch (Exception e) {
            resCode = 500;
            String message = e.getMessage();
            resMsg = "修改宝宝信息失败" + (StringUtils.isNotBlank(message) ? ("(" + message + ")") : "") + "!";
            e.printStackTrace();
            deleteUploadAvatar(uploadAvatarResult);
            return new AppResponse(resMsg, resCode).jsonResponse(false);
        }
    }

    /**
     * 删除宝宝
     *
     * @param appUserId app用户id
     * @param studentId 宝宝id
     * @return
     */
    @Token(validateSign = true)
    @RequestMapping(value = "deleteBaby", method = RequestMethod.GET)
    public String deleteBaby(@RequestParam String appUserId,
                             @RequestParam String studentId) {
        String resMsg = "删除宝宝成功!";
        int resCode = 200;
        try {
            TssStudent tssStudent = this.tssStudentService.get(studentId);
            if (tssStudent != null) {
                DetachedCriteria dc = DetachedCriteria.forClass(TssAppUserCorrelationBaby.class);
                dc.add(Restrictions.eq("appUserId", appUserId));
                dc.add(Restrictions.eq("studentId", studentId));
                List<TssAppUserCorrelationBaby> appUserCorrelationBabies = this.appUserTssAppUserCorrelationBabyService.findByDetached(dc);
                if (appUserCorrelationBabies != null && !appUserCorrelationBabies.isEmpty()) {
                    List<String> familyMemberIds = new ArrayList<>();
                    for (TssAppUserCorrelationBaby appUserCorrelationBaby : appUserCorrelationBabies) {
                        String familyMemberId = appUserCorrelationBaby.getFamilyMemberId();
                        familyMemberIds.add(familyMemberId);
                    }
                    this.appUserTssAppUserCorrelationBabyService.deleteBaby(appUserCorrelationBabies, familyMemberIds);
                    return new AppResponse(resMsg, resCode).jsonResponse(false);
                } else {
                    resCode = 303;
                    resMsg = "APP端无法删除非关联的宝宝,若要删除,请联系园所管理人员!";
                    return new AppResponse(resMsg, resCode).jsonResponse(false);
                }
            } else {
                resCode = 303;
                resMsg = "宝宝信息不存在!";
                return new AppResponse(resMsg, resCode).jsonResponse(false);
            }
        } catch (Exception e) {
            resCode = 500;
            String message = e.getMessage();
            resMsg = "删除宝宝失败" + (StringUtils.isNotBlank(message) ? ("(" + message + ")") : "") + "!";
            e.printStackTrace();
        }
        return new AppResponse(resMsg, resCode).jsonResponse(false);

    }

    /**
     * 查看用户信息
     *
     * @param appUserId app 用户id
     * @return
     */
    @Token(validateSign = true)
    @RequestMapping(value = "userDetails", method = RequestMethod.GET)
    public String userDetails(@RequestParam String appUserId) {
        String resMsg = "查询用户信息成功!";
        int resCode = 200;
        AppResponse response = new AppResponse();
        try {
            TssAppUser tssAppParents = this.appUserService.get(appUserId);
            response.setData(tssAppParents);
        } catch (Exception e) {
            String message = e.getMessage();
            resCode = 500;
            resMsg = "查询用户信息失败" + (StringUtils.isNotBlank(message) ? ("(" + message + ")") : "") + "!";
            e.printStackTrace();
        }
        response.setResCode(resCode);
        response.setResMsg(resMsg);
        return response.jsonResponse(true);
    }

    /**
     * 修改用户信息
     *
     * @param newAppUser
     * @return
     */
    @Token(validateSign = true)
    @RequestMapping(value = "changeUser", method = RequestMethod.POST)
    public String changeUser(HttpServletRequest request, TssAppUser newAppUser) {
        String resMsg = "修改用户信息成功!";
        int resCode = 200;
        if (StringUtils.isBlank(newAppUser.getId())) {
            resMsg = "appUserId必传!";
            return new AppResponse(resMsg, 301).jsonResponse(false);
        }
        TssAppUser appUser = this.appUserService.get(newAppUser.getId());
        if (appUser == null) {
            resMsg = "用户不存在!";
            return new AppResponse(resMsg, 301).jsonResponse(false);
        }
        try {
            BeanUtils.copyProperties(newAppUser, appUser, false, "phoneNum", "password", "avatar", "registerClientSysType", "createTime", "version");
            UploadAvatarResult uploadAvatarResult = uploadAvatar(request);
            if (StringUtils.isNotBlank(uploadAvatarResult)) {
                String avatar = uploadAvatarResult.getAvatar();
                if (StringUtils.isNotBlank(avatar)) {
                    appUser.setAvatar(avatar);
                }
            }
            appUserService.updateEntitiy(appUser);
        } catch (Exception e) {
            String message = e.getMessage();
            resCode = 500;
            resMsg = "修改用户信息失败!" + (StringUtils.isNotBlank(message) ? ("(" + message + ")") : "") + "!";
            e.printStackTrace();
        }
        return new AppResponse(resMsg, resCode, appUser).jsonResponse(true);
    }

    public static class UploadAvatarResult {
        DefaultPutRet defaultPutRet;
        private String avatar;

        public DefaultPutRet getDefaultPutRet() {
            return defaultPutRet;
        }

        public void setDefaultPutRet(DefaultPutRet defaultPutRet) {
            this.defaultPutRet = defaultPutRet;
        }

        public String getAvatar() {
            return avatar;
        }

        public void setAvatar(String avatar) {
            this.avatar = avatar;
        }
    }

    /**
     * 删除上传的头像
     *
     * @param uploadAvatarResult 上传结果
     */
    private void deleteUploadAvatar(UploadAvatarResult uploadAvatarResult) {
        if (uploadAvatarResult != null) {
            DefaultPutRet defaultPutRet = uploadAvatarResult.getDefaultPutRet();
            if (defaultPutRet != null) {
                String key = defaultPutRet.key;
                if (StringUtils.isNotBlank(key)) {
                    info("正在删除头像...");
                    QiNiuUtil.delete(key, new QiNiuUtil.QiNiuDeleteFileCallback() {
                        @Override
                        public void execute(Object response) {
                            info("头像删除结果：" + response);
                        }
                    });
                }
            }
        }
    }

    /**
     * 上传头像
     *
     * @param request 请求对象
     * @throws IOException
     */
    private UploadAvatarResult uploadAvatar(HttpServletRequest request) {
        if (ServletFileUpload.isMultipartContent(request)) {
            SysConfig qiniuDominConfig = SysConfigInitializer.getConfigByConfigName("qiniu.domain");
            if (qiniuDominConfig != null) {
                MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) request;
                MultiValueMap<String, MultipartFile> multiFileMap = multipartHttpServletRequest.getMultiFileMap();
                MultipartFile firstFile = multiFileMap.getFirst("file");
                if (firstFile != null) {
                    File tempFile = null;
                    try {
                        String originalFilename = firstFile.getOriginalFilename();
                        String suffix = "." + StringUtils.substringAfterLast(originalFilename, ".");
                        tempFile = File.createTempFile(SequenceUtil.getUpperCaseUUID(), suffix);
                        FileUtils.copyInputStreamToFile(firstFile.getInputStream(), tempFile);
                        DefaultPutRet upload = QiNiuUtil.upload(tempFile);
                        String qiniuDomin = qiniuDominConfig.getValue();
                        qiniuDomin = (qiniuDomin.startsWith("http://") || qiniuDomin.startsWith("https://")) ? qiniuDomin : ("http://" + qiniuDomin);
                        qiniuDomin = qiniuDomin.endsWith("/") ? qiniuDomin : (qiniuDomin + "/");
                        String avatar = qiniuDomin + upload.key;
                        //设置上传后的地址
                        info("头像上传成功,地址：" + avatar);
                        UploadAvatarResult uploadAvatarResult = new UploadAvatarResult();
                        uploadAvatarResult.setAvatar(avatar);
                        uploadAvatarResult.setDefaultPutRet(upload);
                        return uploadAvatarResult;
                    } catch (IOException e) {
                        throw new RuntimeException("头像上传失败!");
                    } finally {
                        if (tempFile != null) {
                            FileUtils.deleteQuietly(tempFile);
                        }
                    }
                }
            } else {
                throw new RuntimeException("头像上传失败,服务器端未配置上传相关参数!");
            }
        }
        return null;
    }
}